home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / scsi / scsi_debug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  14.0 KB  |  516 lines

  1. /* $Id: scsi_debug.c,v 1.1 1992/07/24 06:27:38 root Exp root $
  2.  *  linux/kernel/scsi_debug.c
  3.  *
  4.  *  Copyright (C) 1992  Eric Youngdale
  5.  *  Simulate a host adapter with 2 disks attached.  Do a lot of checking
  6.  *  to make sure that we are not getting blocks mixed up, and panic if
  7.  *  anything out of the ordinary is seen.
  8.  */
  9.  
  10. #include <linux/kernel.h>
  11. #include <linux/sched.h>
  12. #include <linux/timer.h>
  13. #include <linux/head.h>
  14. #include <linux/types.h>
  15. #include <linux/string.h>
  16. #include <linux/genhd.h>
  17. #include <linux/fs.h>
  18.  
  19. #include <asm/system.h>
  20. #include <asm/io.h>
  21.  
  22. #include "../block/blk.h"
  23. #include "scsi.h"
  24. #include "hosts.h"
  25.  
  26. /* Number of real scsi disks that will be detected ahead of time */
  27. static int NR_REAL=-1;
  28.  
  29. #define MAJOR_NR SCSI_DISK_MAJOR
  30. #define START_PARTITION 4
  31. #define SCSI_DEBUG_TIMER 20
  32. /* Number of jiffies to wait before completing a command */
  33. #define DISK_SPEED     10
  34. #define CAPACITY (0x80000)
  35.  
  36. static int starts[] = {4, 1000, 50000, CAPACITY, 0};
  37. static int npart = 0;
  38.  
  39. #include "scsi_debug.h"
  40. #ifdef DEBUG
  41. #define DEB(x) x
  42. #else
  43. #define DEB(x)
  44. #endif
  45.  
  46. #define VERIFY1_DEBUG(RW)                               \
  47.       if (bufflen != 1024) {printk("%d", bufflen); panic("(1)Bad bufflen");};            \
  48.       start = 0;                            \
  49.       if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1];        \
  50.       if (bh){                            \
  51.     if (bh->b_size != 1024) panic ("Wrong bh size");    \
  52.     if ((bh->b_blocknr << 1) + start != block)               \
  53.       {  printk("Wrong bh block# %d %d ",bh->b_blocknr, block);  \
  54.       panic ("Wrong bh block#");};  \
  55.     if (bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
  56.       };
  57.  
  58. #if 0
  59. /* This had been in the VERIFY_DEBUG macro, but it fails if there is already
  60.    a disk on the system */
  61.       if ((SCpnt->request.dev & 0xfff0) != ((target + NR_REAL) << 4) +(MAJOR_NR << 8)){    \
  62.     printk("Dev #s %x %x ",SCpnt->request.dev, target);            \
  63.     panic ("Bad target");};                        \
  64.  
  65. #endif
  66.  
  67. #define VERIFY_DEBUG(RW)                               \
  68.       if (bufflen != 1024 && (!SCpnt->use_sg)) {printk("%x %d\n ",bufflen, SCpnt->use_sg); panic("Bad bufflen");};       \
  69.       start = 0;                            \
  70.       if ((SCpnt->request.dev & 0xf) > npart) panic ("Bad partition");    \
  71.       if ((SCpnt->request.dev & 0xf) != 0) start = starts[(SCpnt->request.dev & 0xf) - 1];        \
  72.       if (SCpnt->request.cmd != RW) panic ("Wrong  operation");        \
  73.       if (SCpnt->request.sector + start != block) panic("Wrong block.");    \
  74.       if (SCpnt->request.current_nr_sectors != 2 && (!SCpnt->use_sg)) panic ("Wrong # blocks");    \
  75.       if (SCpnt->request.bh){                            \
  76.     if (SCpnt->request.bh->b_size != 1024) panic ("Wrong bh size");    \
  77.     if ((SCpnt->request.bh->b_blocknr << 1) + start != block)               \
  78.       {  printk("Wrong bh block# %d %d ",SCpnt->request.bh->b_blocknr, block);  \
  79.       panic ("Wrong bh block#");};  \
  80.     if (SCpnt->request.bh->b_dev != SCpnt->request.dev) panic ("Bad bh target");\
  81.       };
  82.  
  83. static volatile void (*do_done[SCSI_DEBUG_MAILBOXES])(Scsi_Cmnd *) = {NULL, };
  84. static int scsi_debug_host = 0;
  85. extern void scsi_debug_interrupt();
  86.  
  87. volatile Scsi_Cmnd * SCint[SCSI_DEBUG_MAILBOXES] = {NULL,};
  88. static volatile unsigned int timeout[SCSI_DEBUG_MAILBOXES] ={0,};
  89.  
  90. static char sense_buffer[128] = {0,};
  91.  
  92. static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){
  93.   int i;
  94. #if 0
  95.   unsigned char * pnt;
  96. #endif
  97.   unsigned int * lpnt;
  98.   struct scatterlist * sgpnt = NULL;
  99.   printk("use_sg: %d",SCpnt->use_sg);
  100.   if (SCpnt->use_sg){
  101.     sgpnt = (struct scatterlist *) SCpnt->buffer;
  102.     for(i=0; i<SCpnt->use_sg; i++) {
  103.       lpnt = (int *) sgpnt[i].alt_address;
  104.       printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
  105.       if (lpnt) printk(" (Alt %x) ",lpnt[15]);
  106.     };
  107.   } else {
  108.     printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
  109.        SCpnt->bufflen);
  110.     lpnt = (int *) SCpnt->request.buffer;
  111.     if (lpnt) printk(" (Alt %x) ",lpnt[15]);
  112.   };
  113.   lpnt = (unsigned int *) SCpnt;
  114.   for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
  115.     if ((i & 7) == 0) printk("\n");
  116.     printk("%x ",*lpnt++);
  117.   };
  118.   printk("\n");
  119.   if (flag == 0) return;
  120.   lpnt = (unsigned int *) sgpnt[0].alt_address;
  121.   for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
  122.     if ((i & 7) == 0) printk("\n");
  123.     printk("%x ",*lpnt++);
  124.   };
  125. #if 0
  126.   printk("\n");
  127.   lpnt = (unsigned int *) sgpnt[0].address;
  128.   for (i=0;i<sizeof(Scsi_Cmnd)/4+1; i++) {
  129.     if ((i & 7) == 0) printk("\n");
  130.     printk("%x ",*lpnt++);
  131.   };
  132.   printk("\n");
  133. #endif
  134.   printk("DMA free %d sectors.\n", dma_free_sectors);
  135. }
  136.  
  137. int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
  138. {
  139.     unchar *cmd = (unchar *) SCpnt->cmnd;
  140.     struct partition * p;
  141.     int block, start;
  142.     struct buffer_head * bh = NULL;
  143.     unsigned char * buff;
  144.     int nbytes, sgcount;
  145.     int scsi_debug_errsts;
  146.     struct scatterlist * sgpnt;
  147.     int target = SCpnt->target;
  148.     int bufflen = SCpnt->request_bufflen;
  149.     int i;
  150.     sgcount = 0;
  151.     sgpnt = NULL;
  152.  
  153.     DEB(if (target > 1) { SCpnt->result = DID_TIME_OUT << 16;done(SCpnt);return 0;});
  154.     
  155.     buff = (unsigned char *) SCpnt->request_buffer;
  156.  
  157.     if(target>=2 || SCpnt->lun != 0) {
  158.       SCpnt->result =  DID_NO_CONNECT << 16;
  159.       done(SCpnt);
  160.       return 0;
  161.     };
  162.     
  163.     switch(*cmd){
  164.     case REQUEST_SENSE:
  165.       printk("Request sense...\n");
  166. #ifndef DEBUG
  167.       { int i;
  168.     printk("scsi_debug: Requesting sense buffer (%x %x %x %d):", SCpnt, buff, done, bufflen);
  169.     for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
  170.     printk("\n");
  171.       };
  172. #endif
  173.       memset(buff, 0, bufflen);
  174.       memcpy(buff, sense_buffer, bufflen);
  175.       memset(sense_buffer, 0, sizeof(sense_buffer));
  176.       SCpnt->result = 0;
  177.       done(SCpnt); 
  178.       return 0;
  179.     case ALLOW_MEDIUM_REMOVAL:
  180.       if(cmd[4]) printk("Medium removal inhibited...");
  181.       else printk("Medium removal enabled...");
  182.       scsi_debug_errsts = 0;
  183.       break;
  184.     case INQUIRY:
  185.       printk("Inquiry...(%x %d)\n", buff, bufflen);
  186.       memset(buff, 0, bufflen);
  187.       buff[0] = TYPE_DISK;
  188.       buff[1] = 0x80;  /* Removable disk */
  189.       buff[2] = 1;
  190.       memcpy(&buff[8],"Foo Inc",7);
  191.       memcpy(&buff[16],"XYZZY",5);
  192.       memcpy(&buff[32],"1",1);
  193.       scsi_debug_errsts = 0;
  194.       break;
  195.     case TEST_UNIT_READY:
  196.       printk("Test unit ready.\n");
  197.       if (buff)
  198.     memset(buff, 0, bufflen);
  199.       scsi_debug_errsts = 0;
  200.       break;
  201.     case READ_CAPACITY:
  202.       printk("Read Capacity\n");
  203.       if(NR_REAL < 0) NR_REAL = (SCpnt->request.dev >> 4) & 0x0f;
  204.       memset(buff, 0, bufflen);
  205.       buff[0] = (CAPACITY >> 24);
  206.       buff[1] = (CAPACITY >> 16) & 0xff;
  207.       buff[2] = (CAPACITY >> 8) & 0xff;
  208.       buff[3] = CAPACITY & 0xff;
  209.       buff[6] = 2; /* 512 byte sectors */
  210.       scsi_debug_errsts = 0;
  211.       break;
  212.     case READ_10:
  213.     case READ_6:
  214. #ifdef DEBUG
  215.       printk("Read...");
  216. #endif
  217.       if ((*cmd) == READ_10)
  218.     block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); 
  219.       else 
  220.     block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
  221.       VERIFY_DEBUG(READ);
  222.       printk("(r%d)",SCpnt->request.nr_sectors);
  223.       nbytes = bufflen;
  224.       if(SCpnt->use_sg){
  225.     sgcount = 0;
  226.     sgpnt = (struct scatterlist *) buff;
  227.     buff = sgpnt[sgcount].address;
  228.     bufflen = sgpnt[sgcount].length;
  229.     bh = SCpnt->request.bh;
  230.       };
  231.       scsi_debug_errsts = 0;
  232.       do{
  233.     VERIFY1_DEBUG(READ);
  234.     memset(buff, 0, bufflen);
  235. /* If this is block 0, then we want to read the partition table for this
  236.    device.  Let's make one up */
  237.     if(block == 0 && target == 0) {
  238.       *((unsigned short *) (buff+510)) = 0xAA55;
  239.       p = (struct partition* ) (buff + 0x1be);
  240.       npart = 0;
  241.       while(starts[npart+1]){
  242.         p->start_sect = starts[npart];
  243.         p->nr_sects = starts[npart+1] - starts [npart];
  244.         p->sys_ind = 0x81;  /* Linux partition */
  245.         p++;
  246.         npart++;
  247.       };
  248.       scsi_debug_errsts = 0;
  249.       break;
  250.     };
  251. #ifdef DEBUG
  252.     if (SCpnt->use_sg) printk("Block %x (%d %d)\n",block, SCpnt->request.nr_sectors,
  253.            SCpnt->request.current_nr_sectors);
  254. #endif
  255.     /* Simulate a disk change */
  256.     if(block == 0xfff0) {
  257.       sense_buffer[0] = 0x70;
  258.       sense_buffer[2] = UNIT_ATTENTION;
  259.       starts[0] += 10;
  260.       starts[1] += 10;
  261.       starts[2] += 10;
  262.      
  263. #ifdef DEBUG
  264.       { int i;
  265.     printk("scsi_debug: Filling sense buffer:");
  266.     for(i=0;i<12;i++) printk("%d ",sense_buffer[i]);
  267.     printk("\n");
  268.       };
  269. #endif
  270.       scsi_debug_errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
  271.       break;
  272.     } /* End phony disk change code */
  273.     memset(buff, 0, bufflen);
  274.     memcpy(buff, &target, sizeof(target));
  275.     memcpy(buff+sizeof(target), cmd, 24);
  276.     memcpy(buff+60, &block, sizeof(block));
  277.     memcpy(buff+64, SCpnt, sizeof(Scsi_Cmnd));
  278.     nbytes -= bufflen;
  279.     if(SCpnt->use_sg){
  280.       memcpy(buff+128, bh, sizeof(struct buffer_head));
  281.       block += bufflen >> 9;
  282.       bh = bh->b_reqnext;
  283.       sgcount++;
  284.       if (nbytes) {
  285.         if(!bh) panic("Too few blocks for linked request.");
  286.         buff = sgpnt[sgcount].address;
  287.         bufflen = sgpnt[sgcount].length;
  288.       };
  289.     }
  290.       } while(nbytes);
  291.       if (SCpnt->use_sg && !scsi_debug_errsts)
  292.     if(bh) scsi_dump(SCpnt, 0);
  293.       break;
  294.     case WRITE_10:
  295.     case WRITE_6:
  296. #ifdef DEBUG
  297.       printk("Write\n");
  298. #endif
  299.       if ((*cmd) == WRITE_10)
  300.     block = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); 
  301.       else 
  302.     block = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
  303.       VERIFY_DEBUG(WRITE);
  304.       printk("(w%d)",SCpnt->request.nr_sectors);
  305.       if (SCpnt->use_sg){
  306.     if ((bufflen >> 9) != SCpnt->request.nr_sectors)
  307.       panic ("Trying to write wrong number of blocks\n");
  308.     sgpnt = (struct scatterlist *) buff;
  309.     buff = sgpnt[sgcount].address;
  310.       };
  311. #if 0
  312.       if (block != *((unsigned long *) (buff+60))) {
  313.     printk("%x %x :",block,  *((unsigned long *) (buff+60)));
  314.     scsi_dump(SCpnt,1);
  315.     panic("Bad block written.\n");
  316.       };
  317. #endif
  318.       scsi_debug_errsts = 0;
  319.       break;
  320.      default:
  321.       printk("Unknown command %d\n",*cmd);
  322.       SCpnt->result =  DID_NO_CONNECT << 16;
  323.       done(SCpnt);
  324.       return 0;
  325.     };
  326.  
  327.     cli();
  328.     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
  329.       if (SCint[i] == 0) break;
  330.     };
  331.  
  332.     if (i >= SCSI_DEBUG_MAILBOXES || SCint[i] != 0) 
  333.       panic("Unable to find empty SCSI_DEBUG command slot.\n");
  334.  
  335.     SCint[i] = SCpnt;
  336.  
  337.     if (done) {
  338.     DEB(printk("scsi_debug_queuecommand: now waiting for interrupt "););
  339.     if (do_done[i])
  340.       printk("scsi_debug_queuecommand: Two concurrent queuecommand?\n");
  341.     else
  342.       do_done[i] = done;
  343.     }
  344.     else
  345.       printk("scsi_debug_queuecommand: done cant be NULL\n");
  346.  
  347.     timeout[i] = jiffies+DISK_SPEED;
  348.  
  349. /* If no timers active, then set this one */
  350.     if ((timer_active & (1 << SCSI_DEBUG_TIMER)) == 0) {
  351.       timer_table[SCSI_DEBUG_TIMER].expires = timeout[i];
  352.       timer_active |= 1 << SCSI_DEBUG_TIMER;
  353.     };
  354.  
  355.     SCpnt->result = scsi_debug_errsts;
  356.     sti();
  357.  
  358. #if 0
  359.     printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
  360. #endif
  361.  
  362.     return 0;
  363. }
  364.  
  365. volatile static int internal_done_flag = 0;
  366. volatile static int internal_done_errcode = 0;
  367. static void internal_done(Scsi_Cmnd * SCpnt)
  368. {
  369.     internal_done_errcode = SCpnt->result;
  370.     ++internal_done_flag;
  371. }
  372.  
  373. int scsi_debug_command(Scsi_Cmnd * SCpnt)
  374. {
  375.     DEB(printk("scsi_debug_command: ..calling scsi_debug_queuecommand\n"));
  376.     scsi_debug_queuecommand(SCpnt, internal_done);
  377.  
  378.     while (!internal_done_flag);
  379.     internal_done_flag = 0;
  380.     return internal_done_errcode;
  381. }
  382.  
  383. /* A "high" level interrupt handler.  This should be called once per jiffy
  384.  to simulate a regular scsi disk.  We use a timer to do this. */
  385.  
  386. static void scsi_debug_intr_handle(void)
  387. {
  388.     Scsi_Cmnd * SCtmp;
  389.     int i, pending;
  390.     void (*my_done)(Scsi_Cmnd *); 
  391.    int to;
  392.  
  393.     timer_table[SCSI_DEBUG_TIMER].expires = 0;
  394.     timer_active &= ~(1 << SCSI_DEBUG_TIMER);
  395.  
  396.   repeat:
  397.     cli();
  398.     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
  399.       if (SCint[i] == 0) continue;
  400.       if (timeout[i] == 0) continue;
  401.       if (timeout[i] <= jiffies) break;
  402.     };
  403.  
  404.     if(i == SCSI_DEBUG_MAILBOXES){
  405.       pending = INT_MAX;
  406.       for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
  407.     if (SCint[i] == 0) continue;
  408.     if (timeout[i] == 0) continue;
  409.     if (timeout[i] <= jiffies) {sti(); goto repeat;};
  410.     if (timeout[i] > jiffies) {
  411.       if (pending > timeout[i]) pending = timeout[i];
  412.       continue;
  413.     };
  414.       };
  415.       if (pending && pending != INT_MAX) {
  416.     timer_table[SCSI_DEBUG_TIMER].expires = 
  417.       (pending <= jiffies ? jiffies+1 : pending);
  418.     timer_active |= 1 << SCSI_DEBUG_TIMER;
  419.       };
  420.       sti();
  421.       return;
  422.     };
  423.  
  424.     if(i < SCSI_DEBUG_MAILBOXES){
  425.       timeout[i] = 0;
  426.       my_done = do_done[i];
  427.       do_done[i] = NULL;
  428.       to = timeout[i];
  429.       timeout[i] = 0;
  430.       SCtmp = (Scsi_Cmnd *) SCint[i];
  431.       SCint[i] = NULL;
  432.       sti();
  433.  
  434.       if (!my_done) {
  435.     printk("scsi_debug_intr_handle: Unexpected interrupt\n"); 
  436.     return;
  437.       }
  438.       
  439. #ifdef DEBUG
  440.       printk("In intr_handle...");
  441.       printk("...done %d %x %d %d\n",i , my_done, to, jiffies);
  442.       printk("In intr_handle: %d %x %x\n",i, SCtmp, my_done);
  443. #endif
  444.  
  445.       my_done(SCtmp);
  446. #ifdef DEBUG
  447.       printk("Called done.\n");
  448. #endif
  449.     };
  450.     goto repeat;
  451. }
  452.  
  453.  
  454. int scsi_debug_detect(int hostnum)
  455. {
  456.     scsi_debug_host = hostnum;
  457.     timer_table[SCSI_DEBUG_TIMER].fn = scsi_debug_intr_handle;
  458.     timer_table[SCSI_DEBUG_TIMER].expires = 0;
  459.     return 1;
  460. }
  461.  
  462. int scsi_debug_abort(Scsi_Cmnd * SCpnt,int i)
  463. {
  464.     int j;
  465.     void (*my_done)(Scsi_Cmnd *);
  466.     DEB(printk("scsi_debug_abort\n"));
  467.     SCpnt->result = i << 16;
  468.     for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
  469.       if(SCpnt == SCint[j]) {
  470.     my_done = do_done[j];
  471.     my_done(SCpnt);
  472.     cli();
  473.     timeout[j] = 0;
  474.     SCint[j] = NULL;
  475.     do_done[j] = NULL;
  476.     sti();
  477.       };
  478.     };
  479.     return 0;
  480. }
  481.  
  482. int scsi_debug_biosparam(int size, int* info){
  483.   info[0] = 32;
  484.   info[1] = 64;
  485.   info[2] = (size + 2047) >> 11;
  486.   if (info[2] >= 1024) info[2] = 1024;
  487.   return 0;
  488. }
  489.  
  490. int scsi_debug_reset(Scsi_Cmnd * SCpnt)
  491. {
  492.     int i;
  493.     void (*my_done)(Scsi_Cmnd *);
  494.     DEB(printk("scsi_debug_reset called\n"));
  495.     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
  496.       if (SCint[i] == NULL) continue;
  497.       SCint[i]->result = DID_ABORT << 16;
  498.       my_done = do_done[i];
  499.       my_done(SCint[i]);
  500.       cli();
  501.       SCint[i] = NULL;
  502.       do_done[i] = NULL;
  503.       timeout[i] = 0;
  504.       sti();
  505.     };
  506.     return 0;
  507. }
  508.  
  509. char *scsi_debug_info(void)
  510. {
  511.     static char buffer[] = " ";            /* looks nicer without anything here */
  512.     return buffer;
  513. }
  514.  
  515.  
  516.